
#include "GLES2_Base.h"


/////////////////////////////////////
////          Struct part        ////
/////////////////////////////////////


GLES2_Base_Conf::GLES2_Base_Conf() : Draw_Base_Conf()
{
}

const char GLES2_Base_Conf::m_pFragmentShader[] =
	"attribute vec4 vPosition;\n"
	"void main() {\n"
	"  gl_Position = vPosition;\n"
	"}\n";

const char GLES2_Base_Conf::m_pVertexShader[] =
	"precision mediump float;\n"
	"void main() {\n"
	"  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
	"}\n";


/////////////////////////////////////
////          Class part         ////
/////////////////////////////////////

GLES2_Base::GLES2_Base() : Draw_Base()
{
    m_sGLES2_Base_Conf = new GLES2_Base_Conf();
}


int GLES2_Base::loadShader(GLenum a_eShaderType, const char* a_pSource)
{
    GLuint _nShader = glCreateShader(a_eShaderType);
    if (_nShader)
    {
	// 覆盖着色器的的源代码
	glShaderSource(_nShader, 1, &a_pSource, NULL);
	// 编译着色器中的源代码
	glCompileShader(_nShader);
	GLint _nCompiled = 0;
	// 查看编译是否成功
        glGetShaderiv(_nShader, GL_COMPILE_STATUS, &_nCompiled);
	if(!_nCompiled)
	{
	    GLint _InfoLen = 0;
	    // 获取错误信息长度
            glGetShaderiv(_nShader, GL_INFO_LOG_LENGTH, &_InfoLen);
	    if (_InfoLen)
	    {
                char* _Buf = (char*) malloc(_InfoLen);
                if (_Buf)
		{
		    // 可开辟足够空间来存储错误信息
                    glGetShaderInfoLog(_nShader, _InfoLen, NULL, _Buf);
                    LOGE("Could not compile shader %d:\n%s\n",
                            a_eShaderType, _Buf);
                    free(_Buf);
                }
		// 删除着色器
		glDeleteShader(_nShader);
                _nShader = 0;
	    }
	}
    }
    return _nShader;
}


int GLES2_Base::createProgram()
{
	
    GLuint _VertexShader = loadShader(GL_VERTEX_SHADER, m_sGLES2_Base_Conf->m_pVertexShader);
    if (!_VertexShader) {
        return 0;
    }

    GLuint _PixelShader = loadShader(GL_FRAGMENT_SHADER, m_sGLES2_Base_Conf->m_pFragmentShader);
    if (!_PixelShader) {
        return 0;
    }
    
    m_sGLES2_Base_Conf->m_nProgram = glCreateProgram();
    if (m_sGLES2_Base_Conf->m_nProgram) {
        glAttachShader(m_sGLES2_Base_Conf->m_nProgram, _VertexShader);
        checkGlError("glAttachShader");
        glAttachShader(m_sGLES2_Base_Conf->m_nProgram, _PixelShader);
        checkGlError("glAttachShader");
	// 链接着色器程序 
        glLinkProgram(m_sGLES2_Base_Conf->m_nProgram);
        GLint _nlinkStatus = GL_FALSE;
	// 判断链接是否成功的操作 
        glGetProgramiv(m_sGLES2_Base_Conf->m_nProgram, GL_LINK_STATUS, &_nlinkStatus);
        if (_nlinkStatus != GL_TRUE) {
            GLint _nBufLength = 0;
            glGetProgramiv(m_sGLES2_Base_Conf->m_nProgram, GL_INFO_LOG_LENGTH, &_nBufLength);
            if (_nBufLength) {
                char* _cBuf = (char*) malloc(_nBufLength);
                if (_cBuf) {
                    glGetProgramInfoLog(m_sGLES2_Base_Conf->m_nProgram, _nBufLength, NULL, _cBuf);
                    LOGE("Could not link m_sGLES2_Base_Conf->m_nProgram:\n%s\n", _cBuf);
                    free(_cBuf);
                }
            }
            glDeleteProgram(m_sGLES2_Base_Conf->m_nProgram);
            m_sGLES2_Base_Conf->m_nProgram = 0;
        }
    }
    return m_sGLES2_Base_Conf->m_nProgram;
}

void GLES2_Base::draw()
{
    glViewport(0, 0, 320, 480);
    static float grey;
    grey += 0.01f;
    if (grey > 1.0f) {
        grey = 0.0f;
    }
    glClearColor(grey, grey, grey, 1.0f);
    checkGlError("glClearColor");
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    checkGlError("glClear");
    glUseProgram(m_sGLES2_Base_Conf->m_nProgram);
    checkGlError("glUseProgram");
    
    const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
        0.5f, -0.5f };
    
    GLuint gvPositionHandle = glGetAttribLocation(m_sGLES2_Base_Conf->m_nProgram, "vPosition");
    
    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
    checkGlError("glVertexAttribPointer");
    glEnableVertexAttribArray(gvPositionHandle);
    checkGlError("glEnableVertexAttribArray");
    glDrawArrays(GL_TRIANGLES, 0, 3);
    checkGlError("glDrawArrays");
}


void GLES2_Base::printGLString(const char *name, GLenum s)
{
    const char *v = (const char *) glGetString(s);
    LOGI("GL %s = %s\n", name, v);
}

void GLES2_Base::checkGlError(const char* op)
{
    for (GLint error = glGetError(); error; error
            = glGetError()) {
        LOGI("after %s() glError (0x%x)\n", op, error);
    }
}









